home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / vtkerma1.arc / MSRECV.ASM < prev    next >
Assembly Source File  |  1986-02-13  |  31KB  |  1,106 lines

  1.     PAGE 59, 132
  2.  
  3.     TITLE MSRECV -- Module to Receive a file
  4.  
  5. ; Update 13 Jan 86
  6.  
  7. IF1
  8.  %OUT >> Starting pass 1
  9. ELSE
  10.  %OUT >> Starting pass 2
  11. ENDIF
  12.  
  13.     PUBLIC Read1, Read2, rin21, rfile3, read, updrtr, nak, rrinit
  14.  
  15.     INCLUDE MsDefs.H    
  16.  
  17. DataS    SEGMENT    PUBLIC 'DataS'
  18.  
  19.     EXTRN fcb:byte, data:byte, bufpnt:word, chrcnt:word, curchk:byte
  20.     EXTRN comand:byte, flags:byte, pack:byte, trans:byte, OFilSz:WORD
  21.  
  22. ermes7  DB 'Unable to Receive Initiate$'
  23. ermes8  DB 'Unable to receive file name$'
  24. ermes9  DB 'Unable to receive end of file$'
  25. erms10  DB 'Unable to receive data$'
  26. erms11  DB 'Unable to receive attribute or data$'
  27. erms12  DB 'Not enough room on disk for file$'
  28. ermes7a DB 'Remote '
  29.     Program_name
  30.     DB ': Unable to receive initiate$'
  31. ermes8a DB 'Remote '
  32.     Program_name
  33.     DB ': Unable to receive file name$'
  34. ermes9a DB 'Remote '
  35.     Program_name
  36.     DB ': Unable to receive end of file$'
  37. erms10a DB 'Remote '
  38.     Program_name
  39.     DB ': Unable to receive data$'
  40. erms11a DB 'Remote '
  41.     Program_name
  42.     DB ': Unable to receive attribute or data$'
  43. erms12a    DB 'Remote '
  44.     Program_name
  45.     DB ': Not enough room on disk for file$'
  46. infms1  DB cr,'           Receiving: In progress$'
  47. infms3  DB 'Completed$'
  48. infms4  DB 'Failed$'
  49. infms6  DB 'Interrupted$'
  50. infms7    DB cr,' Percent transferred: 100%$'
  51. filhlp2 DB ' Confirm with carriage return, or specify name '
  52.     DB 'to use for incoming file$'
  53. crlf    DB cr,lf,'$'
  54. temp    dw    0
  55. ATR_KBytes DW    0        ; File size in K, according to file's sender
  56. ATR_Avail DW    0        ; Free space on disk, in K
  57. ATR_Ptr    DW    0        ; Ptr to reading point in attribute string
  58. ATR_End_ptr DW    0        ; Ptr to point we don't read from
  59. ATR_Length DW    0        ; Number of chars in attribute data subfield
  60. ATR_Attribute DB 0        ; ASCII char representing attribute type
  61.  
  62. SPC_Msg1 DB 'The incoming file requires $'
  63. SPC_Msg2 DB ' K bytes of disk space, but$'
  64. SPC_Msg3 DB 'the disk you are using has only $'
  65. SPC_Msg4 DB ' K bytes available.$'
  66. SPC_Msg5 DB 'Please insert a formatted disk which'
  67.      DB ' has enough room for this file.$'
  68. SPC_Msg7 DB 'Type control-C to ABORT, any other key to try a new disk.$'
  69.  
  70. SPC_Addr1 EQU (15*256)+5    ; Locations for messages
  71. SPC_Addr3 EQU (16*256)+5
  72. SPC_Addr5 EQU (18*256)+5
  73. SPC_Addr7 EQU (20*256)+5
  74.  
  75. datas    ends
  76.  
  77. Code    SEGMENT    PUBLIC
  78.  
  79.     EXTRN gofil:near, outbuf:near, fixfcb:near, comnd:near, EOT_bells:NEAR
  80.     EXTRN spack:near, rpack:near, serini:NEAR, Nout:NEAR, poscur:near
  81.     EXTRN spar:near, rpar:near, init:near, init1:near, cxmsg:near
  82.     EXTRN error:near, ptchr:near, PerPos:near, ClearL:near
  83.     EXTRN dodec:near, doenc:near, errpack:near, beep:near
  84.     EXTRN ClrMod:near, Close_transfer_screen:NEAR, Show_packets:NEAR
  85.     EXTRN Show_error:NEAR, Show_status:NEAR, Show_retries:NEAR
  86.     EXTRN Clear_percent_message:NEAR
  87.  
  88.     ASSUME cs:Code, ds:DataS
  89.  
  90.  
  91. ; Update retry count and fall through to send a NAK
  92. nak0:    call updrtr        ; Update retry count
  93.  
  94. nak:    mov ax,pack.pktnum    ; Get the packet number we're waiting for
  95.     mov pack.argblk,ax
  96.     mov pack.argbk1,0
  97.     mov cx,0        ; No data, but this may change
  98.     call doenc        ; So call encode
  99.     mov ah,'N'        ; NAK that packet
  100.     call Spack
  101.      jmp Abort
  102.  
  103.     ret
  104.  
  105. updrtr:    cmp pack.state,'A'    ; Supposed to abort?
  106.     je upd0            ; Yes, don't bother with retry count
  107.     inc pack.numrtr        ; Increment the number of retries
  108.     cmp flags.xflg,1    ; Writing to screen?
  109.     je upd0
  110.  
  111.     call Show_retries    ; Use common routine
  112.  
  113. upd0:    ret
  114.  
  115.  
  116. ; init variables for read..
  117. rrinit    proc    near
  118.     mov pack.numpkt,0    ; Set the number of packets to zero
  119.     mov pack.numrtr,0    ; Set the number of retries to zero
  120.     mov pack.pktnum,0    ; Set the packet number to zero
  121.     mov pack.numtry,0    ; Set the number of tries to zero
  122.     ret
  123. rrinit    endp
  124.  
  125. ;    RECEIVE command  --  Some code moved to the GET routine. [21a] 
  126.  
  127. READ    PROC    NEAR        
  128.     mov comand.cmrflg,1    ; Say we're receiving a file. [21a start]
  129.     mov comand.cmcr,1    ; Allow bare CR after RECEIVE
  130.     mov flags.droflg,0    ; Override default drive flag
  131.     mov flags.nmoflg,0    ; Override file name from other host?
  132.     mov dx,offset fcb    ; Put filename here. 
  133.     mov bx,offset filhlp2    ; Text of help message
  134.     mov ah,cmifi        ; Read in the filename
  135.     call comnd        
  136.      jmp RSkp
  137.     mov comand.cmrflg,0    ; Reset flag
  138.     mov comand.cmcr,0
  139.     mov flags.wldflg,0    ; Just in case
  140.     mov ah,cmcfm        ; Get a confirm
  141.     call comnd
  142.      jmp r
  143.  
  144.     mov pack.state,'R'    ; Set the state to receive initiate
  145.     call Init        ; Clear the screen, put up FT screen
  146.     call rrinit        ; init variables for read
  147.     call serini        ; Initialize serial port. [14]
  148.  
  149.     call Read1        ; Call our routine to do the receive
  150.      nop            ;  He skips usually
  151.      nop
  152.      nop
  153.  
  154.     jmp RSkp        ; Return skip to main KERMIT loop
  155.  
  156.  
  157. ; Routine to perform a RECEIVE of a file (called from here and from MSSERV)
  158.  
  159. Read1:    mov flags.cxzflg,0    ; Reset ^X/^Z flag. [20c] 
  160.     call init1        ; Clear the line and initialize the buffers
  161.  
  162.     mov dx, OFFSET infms1    ; "Receiving: In progress"
  163.     call Show_status    ; Display status
  164.  
  165.     call Show_packets    ; Display packet count
  166.     call ClearL        ; Make sure display looks right
  167.  
  168.     call Show_retries    ;  and number of retries
  169.     call ClearL        ; Likewise
  170.  
  171. read2:    cmp flags.xflg,1    ; Are we receiving to the screen. [21c]
  172.      je read21        ; Skip the screen stuff. [21c]
  173.  
  174.     call Show_packets    ; Display the packet count
  175.  
  176. read21: mov ah,pack.state    ; Get the state. [21c]
  177.     cmp ah,'T'        ; Are we in the aTtribute state?
  178.     jne read23
  179.     call RAttr        ; Waiting for attribute packet or data
  180.     jmp read2
  181. read23:    cmp ah,'D'        ; Are we in the Data receive state?
  182.     jne read3
  183.     call rdata
  184.     jmp read2
  185. read3:  cmp ah,'F'        ; Are we in the file receive state?
  186.     jne read4
  187.     call rfile        ; Call receive file
  188.     jmp read2
  189. read4:  cmp ah,'R'        ; Are we in the receive initiate state?
  190.     jne read5
  191.     call rinit
  192.     jmp read2
  193.  
  194. Read5:  cmp ah,'C'        ; Are we in the receive complete state?
  195.      jne read6
  196.  
  197.     cmp flags.xflg,0    ; Did we write to the screen? [21c]
  198.      je Read5a        ; No so print status. [21c]
  199.  
  200.     mov Flags.xflg, 0    ; Reset it. [21c]
  201.     jmp RSkp        ; Yes, so just return. [21c]
  202.  
  203. Read5a:    cmp Flags.RemFlg,0    ; Remote mode?
  204.      jne Read7a        ;  Yes, don't type anything
  205.  
  206.     cmp Flags.cxzflg, 0    ; completed normally?
  207.      jne Read5b        ;  no, don't bother with this
  208.  
  209.     call PerPos        ; Note that we are now 100% done
  210.     mov ah, PrStr
  211.     mov dx, OFFSET infms7
  212.     int Dos
  213.  
  214.     mov dx, OFFSET InfMs3    ; Message saying success
  215.     jmp SHORT Read5c
  216.  
  217. Read5b: mov dx, OFFSET infms6    ; Say was interrupted
  218.  
  219. Read5c: call Show_status    ; Display the message, whatever it is
  220.     call EOT_bells        ; Make optional noise
  221.     jmp SHORT Read7
  222.  
  223. ; Here, we have some type of error -- clean up and go home
  224.  
  225. read6:    cmp flags.xflg,0    ; Did we write out to screen? [21c]
  226.      je read61        ; No so print status. [21c]
  227.     mov flags.xflg,0    ; Reset it. [21c]
  228.     jmp rskp        ; Print onto screen. [21c]
  229.  
  230. read61:    mov dx,offset infms4    ; Plus a little cuteness
  231.     call Show_status
  232.  
  233. read7:    call Close_transfer_screen ; Clean up for command mode
  234.  
  235. read7a:    jmp rskp
  236.  
  237. READ    ENDP
  238.  
  239.  
  240. ;    Receive routines
  241.  
  242. ;    Receive init
  243.  
  244. RINIT    PROC    NEAR
  245.     mov ah,pack.numtry    ; Get the number of tries
  246.     cmp ah,imxtry        ; Have we reached the maximum number of tries?
  247.     jl rinit2
  248.     mov dx,offset ermes7
  249.     call Show_error        ; Display message
  250.     mov bx,offset ermes7a
  251.     call errpack        ; Send error packet just in case
  252.     jmp abort        ; Change the state to abort
  253. rinit2: inc ah            ; Increment it
  254.     mov pack.numtry,ah    ; Save the updated number of tries
  255.     mov ax,pack.argbk2    ; get packet type if here from get
  256.     cmp flags.getflg,1    ; Have we already read in the packet? [21a] 
  257.     je rin21a        ; Yes, so don't call RPACK. [21a]
  258.     mov ah,trans.chklen
  259.     mov curchk,ah        ; Save checksum length we want to use
  260.     mov trans.chklen,1    ; Use 1 char for init packet
  261.     call rpack        ; Get a packet
  262.      jmp rin22        ; Trashed packet: nak, retry
  263.     push ax
  264.     mov ah,curchk
  265.     mov trans.chklen,ah    ; Reset to desired value
  266.     pop ax
  267. rin21a:    cmp ah,'S'        ; Is it a send initiate packet?
  268.     jne rinit3        ; If not see if its an error
  269. rin21:    mov flags.getflg,0    ; Reset flag. [21a]
  270.     mov ah,pack.numtry    ; Get the number of tries
  271.     mov pack.oldtry,ah    ; Save it
  272.     mov pack.numtry,0    ; Reset the number of tries
  273.     mov ax,pack.argblk    ; Returned packet number.  (Synchronize them.)
  274.     inc ax            ; Increment it
  275.     and ax,3FH        ; Turn off the two high order bits
  276.     mov pack.pktnum,ax    ; Save modulo 64 of the number
  277.     mov bx,pack.numpkt
  278.     inc bx            ; Increment the number of packets
  279.     mov pack.numpkt,bx
  280.     mov ax,pack.argbk1    ; Get the number of arguments received
  281.     mov bx,offset data    ; Get a pointer to the data
  282.     call spar        ; Get the data into the proper variables
  283.     mov bx,offset data    ; Get a pointer to our data block
  284.     call rpar        ; Set up the receive parameters
  285.     xchg ah,al
  286.     mov ah,0
  287.     mov pack.argbk1,ax    ; Store the returned number of arguments
  288.     mov ah,trans.chklen    ; Checksum length we'll use
  289.     mov curchk,ah        ; Save it
  290.     mov trans.chklen,1    ; Use 1 char for init packet
  291.     mov ah,'Y'        ; Acknowledge packet
  292.     call spack        ; Send the packet
  293.      jmp abort
  294.     mov ah,curchk        ; Checksum length we'll use
  295.     mov trans.chklen,ah    ; Reset to desired value
  296.     mov ah,'F'        ; Set the state to file send
  297.     mov pack.state,ah
  298.     ret
  299. rin22:    mov ah,curchk
  300.     mov trans.chklen,ah    ; Reset to desired value
  301.     jmp nak0        ; Try again
  302. rinit3: cmp ah,'E'        ; Is it an error packet?
  303.     jne rinit4
  304.     call error
  305. rinit4:    jmp abort
  306. RINIT    ENDP
  307.  
  308.  
  309. ;    Receive file
  310.  
  311. RFILE    PROC    NEAR
  312.     cmp pack.numtry,maxtry    ; Have we reached the maximum number of tries?
  313.     jl rfile1
  314.     mov dx,offset ermes8
  315.     call Show_error        ; Display message
  316.     mov bx,offset ermes8a
  317.     call errpack        ; Send error packet just in case
  318.     jmp abort        ; Change the state to abort
  319. rfile1: inc pack.numtry        ; Save the updated number of tries
  320.     call rpack        ; Get a packet
  321.      jmp nak0        ;  Trashed packet: nak, retry
  322.     cmp ah,'S'        ; Is it a send initiate packet?
  323.     je rfil10
  324.     call dodec        ; Decode all incoming packets
  325.     jmp rfile2        ;  No, try next type
  326. rfil10:    cmp pack.oldtry,imxtry    ; Have we reached the maximum number of tries?
  327.     jl rfil12        ; If not proceed
  328.     mov dx,offset ermes7
  329.     call Show_error        ; Display message
  330.     mov bx,offset ermes7a
  331.     call errpack        ; Send error packet just in case
  332.     jmp abort        ; Change the state to abort
  333.  
  334. %OUT >> About half way through source file
  335.  
  336. rfil12: inc pack.oldtry        ; Save the updated number of tries
  337.     mov ax,pack.pktnum    ; Get the present packet number
  338.     cmp ax,0        ; Had we wrapped around? [18 start]
  339.     jne rfilx 
  340.     mov ax,64
  341. rfilx:  dec ax            ; Decrement.  [18 end -- new label]
  342.     cmp ax,pack.argblk    ; Is the packet's number one less than now?
  343.     je rfil13
  344.     jmp nak0        ; No, NAK and try again
  345. rfil13: call updrtr        ; Update retry count
  346.     mov pack.numtry,0    ; Reset the number of tries
  347.     mov bx,offset data    ; Get a pointer to our data block
  348.     call rpar        ; Set up the parameter information
  349.     xchg ah,al
  350.     mov ah,0
  351.     mov pack.argbk1,ax    ; Save the number of arguments
  352.     mov ah,'Y'        ; Acknowledge packet
  353.     call spack        ; Send the packet
  354.      jmp abort
  355.     ret
  356. rfile2: cmp ah,'Z'        ; Is it an EOF packet?
  357.     jne rfile3        ;  No, try next type
  358.     cmp pack.oldtry,maxtry    ; Have we reached the maximum number of tries?
  359.     jl rfil21        ; If not proceed
  360.     mov dx,offset ermes9
  361.     call Show_error        ; DIsplay message
  362.     mov bx,offset ermes9a
  363.     call errpack        ; Send error packet just in case
  364.     jmp abort        ; Change the state to abort
  365. rfil21: inc pack.oldtry        ; Increment it
  366.     mov ax,pack.pktnum    ; Get the present packet number
  367.     cmp ax,0        ; Had we wrapped around? [18 start]
  368.     jne rfily
  369.     mov ax,64
  370. rfily:  dec ax            ; Decrement.  [18 end -- new label]
  371.     cmp ax,pack.argblk    ; Is the packet's number one less than now?
  372.     je rfil24
  373.     jmp nak0        ; No, NAK and try again
  374. rfil24: call updrtr        ; Update retry count
  375.     mov pack.numtry,0
  376.     mov pack.argbk1,0    ; No data.  (The packet number is in argblk.)
  377.     mov cx,0
  378.     call doenc
  379.     mov ah,'Y'        ; Acknowledge packet
  380.     call spack        ; Send the packet
  381.      jmp abort
  382.     ret
  383. rfile3: cmp ah,'F'        ; Start of file?
  384.     je rfil31        ; Yes. [21c]
  385.     cmp ah,'X'        ; Text header packet? [21c]
  386.     jne rfile4        ; Neither one. 
  387. rfil31: mov ax,pack.argblk    ; Get the packet number. [21c]
  388.     cmp ax,pack.pktnum    ; Is it the right packet number?
  389.     je rfil32
  390.     jmp nak            ; No, NAK it and try again
  391. rfil32: inc ax            ; Increment the packet number
  392.     and ax,3FH        ; Turn off the two high order bits
  393.     mov pack.pktnum,ax    ; Save modulo 64 of the number
  394.     inc pack.numpkt        ; Increment the number of packets
  395.     call gofil        ; Get a file to write to
  396.      jmp abort
  397.     call init1        ; Initialize all the buffers
  398.     mov ah,pack.numtry    ; Get the number of tries
  399.     mov pack.oldtry,ah    ; Save it
  400.     mov pack.numtry,0    ; Reset the number of tries
  401.     mov pack.argbk1,0    ; No data.  (The packet number is in argblk.)
  402.  
  403.     call Clear_percent_message ; Erase this for now
  404.  
  405.     mov cx,0
  406.     call doenc
  407.     mov ah,'Y'        ; Acknowledge packet
  408.     call spack        ; Send the packet
  409.      jmp abort
  410.  
  411. ;    mov pack.state,'D'
  412.     mov pack.state,'T'    ; Set the state to waiting for aTtribute
  413.  
  414.     ret
  415. rfile4: cmp ah,'B'        ; End of transmission
  416.     jne rfile5
  417.     mov ax,pack.pktnum
  418.     cmp ax,pack.argblk    ; Do we match?
  419.     je rfil41
  420.     jmp nak            ; No, NAK it and try again
  421. rfil41: mov pack.argbk1,0    ; No data.  (Packet number already in argblk)
  422.     mov cx,0
  423.     call doenc
  424.     mov ah,'Y'        ; Acknowledge packet
  425.     call spack        ; Send the packet
  426.      jmp abort
  427.     mov pack.state,'C'    ; Set the state to complete
  428.     ret
  429. rfile5: cmp ah,'E'        ; Is it an error packet
  430.     jne rfile6
  431.     call error
  432. rfile6: jmp abort
  433. RFILE    ENDP
  434.  
  435.  
  436. ;    Receive attribute or data
  437.  
  438.     PUBLIC RAttr, rdat11, ATR_2, ATR_3, ATR_5, ATR_err
  439.  
  440. RAttr    PROC
  441.  
  442.     cmp pack.numtry,maxtry    ; Get the number of tries
  443.      jae ATR_err        ;  Too many errors, go blow up
  444.  
  445.     inc pack.numtry        ; Save the updated number of tries
  446.     call rpack        ; Get a packet
  447.      jmp nak0        ;  Trashed packet: nak, retry
  448.  
  449.     cmp ah,'D'        ; Is it a data packet?
  450.      jne ATR_2        ;  No, see if it is an Attribute packet
  451.  
  452. ; Deal with Data (D) packet
  453.  
  454.     mov pack.state, 'D'    ; Switch to Data state
  455.     jmp rdat11        ; Go join the RDATA routine
  456.  
  457. ATR_2:    cmp ah, 'A'        ; Attribute packet?
  458.      je ATR_3        ;  Yes
  459.  
  460.     jmp rdata2        ; No, use RDATA code to see what it is
  461.  
  462. ; Deal with Attribute (A) packet
  463.  
  464. ATR_3:    mov ax,pack.pktnum    ; Get the present packet number
  465.     cmp ax,pack.argblk    ; Is the packet's number correct?
  466.      je ATR_7        ;  Yes
  467.  
  468. ; Got the wrong packet number
  469.  
  470.     cmp pack.oldtry,maxtry    ; Have we reached the maximum number of tries?
  471.      jae ATR_err        ;  Too many errors
  472.  
  473.     inc pack.oldtry        ; Save the updated number of tries
  474.  
  475.     mov ax,pack.pktnum
  476.     cmp ax,0        ; Had we wrapped around? [18 start]
  477.      jne ATR_5
  478.  
  479.     mov ax,64
  480.  
  481. ATR_5:    dec ax            ; [14] [18 end -- new label]
  482.     cmp ax,pack.argblk    ; Is the packet's number one less than now?
  483.      je ATR_6        ;  Yes
  484.  
  485.     jmp nak0        ; No, NAK it and try again
  486.  
  487. ; File sender has sent us a second copy of a packet we already ACKed,
  488. ;  which suggests that our ACK was lost.  Send another ACK so we can move
  489. ;  on to the next packet.  This constitutes a retry
  490.  
  491. ATR_6:    call updrtr        ; Update retry count
  492.  
  493.     mov pack.numtry,0    ; Reset number of tries
  494.     mov pack.argbk1,0    ; No data.  (The packet number is in argblk.)
  495.     mov cx,0
  496.  
  497.     call doenc
  498.  
  499.     mov ah,'Y'        ; Acknowledge packet
  500.     call spack        ; Send the packet
  501.      jmp abort
  502.  
  503.     ret
  504.  
  505. ; Common point for error, Too many retries
  506.  
  507. ATR_err:
  508.     mov dx,offset erms11
  509.     call Show_error        ; Display message
  510.     mov bx,offset erms11a
  511.     call errpack        ; Send error packet just in case
  512.     jmp abort        ; Change the state to abort
  513.  
  514.     PUBLIC ATR_7, ATR_8, ATR_9, ATR_10, ATR_LP1, ATR_Ignore
  515.     PUBLIC ATR_Do_filesize
  516.  
  517. ; Have good Attribute packet, the right packet number and everything
  518.  
  519. ATR_7:    inc ax            ; Increment the packet number
  520.     and ax,3FH        ; Turn off the two high order bits
  521.     mov pack.pktnum,ax    ; Save modulo 64 of the number
  522.  
  523.     inc pack.numpkt        ; Increment the number of packets
  524.  
  525.     mov ah,pack.numtry    ; Get the number of tries
  526.     mov pack.oldtry,ah    ; Save it
  527.  
  528. ; Interrupted?
  529.  
  530.     mov ax,pack.argbk1    ; Get the length of the data
  531.     cmp flags.cxzflg,0    ; Has the user typed a ^X or ^Z? [20c]
  532.      je ATR_8        ;  No, keep dealing with Attribute packet
  533.  
  534.     cmp flags.abfflg,1    ; Discard incomplete files?
  535.      je ATR_9        ;  If yes don't write data out to file
  536.  
  537. ; Process the attribute(s) in the packet
  538.  
  539. ATR_8:    mov ax, OFFSET data    ; Where the data comes from
  540.     mov ATR_Ptr, ax        ; Store for reading of attributes strings
  541.  
  542.     add ax, pack.argbk1    ; Add in the length of the data
  543.     mov ATR_End_ptr, ax    ; Store the ending pointer
  544.  
  545. ATR_LP1:
  546.     call ATR_Get_attribute    ; Get the attribute
  547.      jc ATR_9        ;  End of file
  548.  
  549. ; Determine attribute type
  550.  
  551.     cmp ATR_Attribute, "!"    ; Is the attribute the one for file size?
  552.      je ATR_Do_filesize    ;  Yes, go handle it
  553.  
  554. ATR_Ignore:
  555.     mov ax, ATR_Length    ; Get the attr length
  556.     add ATR_Ptr, ax        ; Advance the pointer
  557.     jmp ATR_LP1        ; Go try for another attribute
  558.  
  559. ; Type is "file size in K bytes"
  560.  
  561. ATR_Do_filesize:
  562.     mov cx, ATR_Length    ; Load up number of expected digits
  563.     call ATR_Get_number    ; Get the file size
  564.      jc ATR_9        ;  EOF or non-numeric junk
  565.  
  566.     mov ATR_KBytes, ax    ; Save file size in K bytes
  567.  
  568.     mov dx, ax        ; Copy file size in K to dx
  569.     mov cl, 6        ; This many bits
  570.     shr dx, cl        ; Get high order 10 bits from ax into low
  571.                 ;  order position in dx
  572.     mov cl, 10        ; This many bits
  573.     shl ax, cl        ; Get low order 6 bits from ax into high
  574.                 ;  order position in ax
  575.     mov bx, 100        ; Get a 100 (base of percentage) into bx
  576.     div bx            ; Convert doubleword byte count into percent-
  577.                 ;  adjusted value for PerPr routine
  578.     mov OFilSz, ax        ; Store it away for later
  579.  
  580. ; Jump here after user has inserted a new disk
  581.  
  582. ATR_Try_again:
  583.  
  584.     call ATR_Get_disk_freespace ; See how much space is left on the disk
  585.     mov ATR_Avail, ax    ; Store the answer for possible later display
  586.     cmp ax, ATR_KBytes    ; Enough room for the file?
  587.      jae ATR_LP1        ;  There is enough room, read any other
  588.                 ;  attributes we find
  589.  
  590.     mov ah, ClosF        ; Close the file
  591.     mov dx, OFFSET Fcb
  592.     int Dos
  593.  
  594.     mov ah, DelF        ; Delete it
  595.     int Dos
  596.  
  597.     call ATR_Show_space_problem ; Inform the user, ask for a new disk
  598.  
  599.     mov ah, ConInQ        ; Quiet console input
  600.     int Dos            ; Wait until user hits a key
  601.  
  602.     cmp al, 3        ; Control-C?
  603.      je ATR_Abort        ;  Yes, don't accept the file
  604.  
  605.     call ATR_Make_new_file    ; Create the file on the new disk (blow old
  606.                 ;  file away if it already exists)
  607.  
  608.     call ATR_Fix_screen    ; Get rid of the message
  609.  
  610.     jmp ATR_Try_again    ; Go try again
  611.  
  612. ATR_9:    mov pack.numtry,0    ; Reset the number of tries
  613.     mov pack.argbk1,0    ; No data.  (Packet number still in argblk.)
  614.     sub cx, cx        ; Make a zero
  615.     cmp flags.cxzflg,0    ; Interrupt file transfer? [20c]
  616.      je ATR_10        ; Nope. [20c] 
  617.  
  618.     mov bx,offset data    ; Send data in ACK in case remote... [20c] 
  619.     mov ah,flags.cxzflg    ; ... knows about ^X/^Z. [20c]
  620.     mov [bx],ah        ; Put data into the packet. [20c]
  621.     mov pack.argbk1,1    ; Set data size to 1. [20c]
  622.     mov cx,1
  623.  
  624. ; Successful receipt of an Attribute packet, ACK the packet
  625.  
  626. ATR_10: call doenc
  627.  
  628.     mov ah,'Y'        ; Acknowledge packet
  629.     call spack
  630.      jmp abort
  631.  
  632.     ret            ; Done here
  633.  
  634. ; Routines used to handle attribute packets
  635.  
  636.     PUBLIC ATR_Get_attribute, ATR_Exit_error, ATR_Exit, ATR_Abort
  637.     PUBLIC ATR_Get_a_char, ATR_Get_number, ATR_Get_disk_freespace
  638.     PUBLIC ATR_Show_space_problem
  639.  
  640. ATR_Get_attribute:
  641.     call ATR_Get_a_char    ; Get the attribute character
  642.      jc ATR_Exit        ;  End of file
  643.  
  644.     mov ATR_Attribute, al    ; Store it
  645.  
  646.     call ATR_Get_a_char    ; Get the number of digits in the file size
  647.      jc ATR_Exit        ;  End of file
  648.  
  649.     sub al, 32        ; Convert to true number
  650.     cbw            ; Zero ah
  651.     mov ATR_Length, ax    ; Store the data length
  652.  
  653. ; Make sure that this is a valid length
  654.  
  655.     mov ax, ATR_End_ptr    ; Get ending ptr
  656.     sub ax, ATR_Ptr        ; Get length until end-of-data
  657.     cmp ax, ATR_Length    ; Is size sufficient for this data subfield?
  658.      jl ATR_Exit_error    ;  No, bomb it
  659.  
  660.     clc            ; No error
  661.     ret            ; Return
  662.  
  663. ATR_Exit_error:
  664.     stc            ; Force error flag
  665.  
  666. ATR_Exit:
  667.     ret            ; Return
  668.  
  669. ATR_Abort:
  670.     mov dx,offset erms12
  671.     call Show_error        ; Display message
  672.     mov bx,offset erms12a
  673.     call errpack        ; Send error packet just in case
  674.     jmp abort        ; Change the state to abort
  675.  
  676. ATR_Get_a_char:
  677.  
  678. ;   Returns ... 
  679. ;    Carry set = No char to be found
  680. ;    al/ the character, if any
  681.  
  682.     push si            ; Save reg
  683.     mov si, ATR_Ptr        ; Our reading ptr
  684.     cmp si, ATR_End_ptr    ; Pointing at end-of-data, or higher?
  685.      jb ATR_GCh_1        ;  No, no error
  686.  
  687.     stc            ; Flag the error
  688.     jmp SHORT ATR_GCh_2    ; Finish up
  689.  
  690. ATR_GCh_1:
  691.     cld            ; Forwards
  692.     lodsb            ; Pick up the new character
  693.     mov ATR_Ptr, si        ; Save updated ptr
  694.     clc            ; No error
  695.  
  696. ATR_GCh_2:
  697.     pop si            ; Restore reg
  698.     ret            ; Done here
  699.  
  700. ATR_Get_number:
  701.  
  702. ;   Call with ...
  703. ;    cx/ number of digits to read
  704. ;
  705. ;   Returns ... 
  706. ;    Carry set = No number
  707. ;    ax/ the number, if any
  708.  
  709.     sub bx, bx        ; Clear a working register
  710.  
  711. PN_1:    call ATR_Get_a_char    ; Get a char
  712.      jc ATR_Badnum        ;  None to be got
  713.  
  714.     cmp al, '0'        ; Lower than 0?
  715.      jb ATR_Badnum        ;  Yes, done here
  716.     cmp al, '9'        ; Higher than 9?
  717.      ja ATR_Badnum        ;  Yes, done here
  718.  
  719.     sub al, '0'        ; Make ASCII digit into decimal
  720.     sub ah, ah        ; Clear ah
  721.     xchg ax, bx        ; Swap ax and bx
  722.     mov dx, 10        ; Get a ten
  723.     mul dx            ; Multiply old number by ten
  724.     add bx, ax        ; Add in the new digit
  725.     loop PN_1        ; Go get another char, if more to do
  726.  
  727.     clc            ; We have a number
  728.     mov ax, bx        ; Copy over the number
  729.     ret            ; Done here
  730.  
  731. ATR_Badnum:
  732.     stc            ; No number
  733.     ret            ; Go home
  734.  
  735. ; See how much space is available on the connected disk, returns with ...
  736. ;    ax/ Number of Kilobytes (1024) available on "default" disk
  737.  
  738. ATR_Get_disk_freespace:
  739.     
  740.     sub dl, dl        ; Want data for the default drive
  741.     mov ah, 36h        ; DOS function call for space available
  742.     int DOS            ; Do it .
  743.  
  744.     cmp ax, 0ffffh        ; Invalid drive spec?
  745.      je ATR_DSK_Problem    ;  There is some problem
  746.  
  747. ;   At this point, we have the following ...
  748. ;        ax/ number of sectors per cluster
  749. ;        bx/ number of free clusters
  750. ;        cx/ number of bytes per sector
  751.  
  752.     mul cx            ; ax * cx --> ax, number of bytes per cluster
  753.     mov cl, 9        ; Want to shift right this many bits
  754.     shr ax, cl        ; Divide by 512, so final result will fit in ax
  755.     mul bx            ; ax * bx --> ax, (number of bytes free)/512
  756.     shr ax, 1        ; Divide by 2 to convert this to Kilobytes
  757.     ret            ; Done here
  758.  
  759. ATR_DSK_Problem:
  760.     sub ax, ax        ; Pretend no disk space free
  761.     ret            ; Done here
  762.  
  763. ATR_Show_space_problem:
  764.  
  765. Tmsg    MACRO Message
  766.     mov dx, OFFSET Message
  767.     mov ah, PrStr
  768.     int Dos
  769.     ENDM
  770.  
  771. GoMsg    MACRO Number
  772.     mov dx, SPC_Addr&Number
  773.     call PosCur
  774.     Tmsg SPC_Msg&Number
  775.     ENDM
  776.  
  777.     GoMsg 1
  778.     mov ax, ATR_KBytes
  779.     call Nout
  780.     Tmsg SPC_Msg2
  781.  
  782.     GoMsg 3
  783.     mov ax, ATR_Avail
  784.     call Nout
  785.     Tmsg SPC_Msg4
  786.  
  787.     GoMsg 5
  788.     GoMsg 7
  789.  
  790.     jmp Beep        ; Go make a noise, ret from there
  791.  
  792. ATR_Make_new_file:
  793.  
  794.     mov ah, DelF        ; Delete the file if it exists
  795.     mov dx, OFFSET Fcb
  796.     int Dos
  797.  
  798.     mov ah, MakeF        ; Now create it
  799.     int Dos
  800.  
  801.     ret
  802.  
  803. ATR_Fix_screen:
  804.  
  805. Clear_it MACRO Address
  806.     mov dx, Address        ;; Position
  807.     call PosCur        ;; Go there
  808.     call ClearL        ;; Clear out any existing message
  809.     ENDM
  810.  
  811.     Clear_it SPC_Addr1    ; Clear each line
  812.     Clear_it SPC_Addr3
  813.     Clear_it SPC_Addr5
  814.     Clear_it SPC_Addr7
  815.  
  816.     ret
  817.  
  818. RAttr    ENDP
  819.  
  820.  
  821. ;    Receive data
  822.  
  823. RDATA    PROC
  824.  
  825.     cmp pack.numtry,maxtry    ; Get the number of tries
  826.      jl rdata1
  827.  
  828.     mov dx,offset erms10
  829.     call Show_error        ; Display message
  830.     mov bx,offset erms10a
  831.     call errpack        ; Send error packet just in case
  832.     jmp abort        ; Change the state to abort
  833.  
  834. rdata1: inc pack.numtry        ; Save the updated number of tries
  835.     call rpack        ; Get a packet
  836.      jmp Nak0        ;  Trashed packet: nak, retry
  837.  
  838.     cmp ah,'D'        ; Is it a data packet?
  839.     je rdat11
  840.  
  841.     call dodec        ; Decode data
  842.     jmp rdata2        ;  No, try next type
  843.  
  844. rdat11: mov ax,pack.pktnum    ; Get the present packet number
  845.     cmp ax,pack.argblk    ; Is the packet's number correct?
  846.     jz rdat14
  847.  
  848.     cmp pack.oldtry,maxtry    ; Have we reached the maximum number of tries?
  849.     jl rdat12        ; If not proceed
  850.  
  851.     mov dx,offset erms10
  852.     call Show_error        ; Display message
  853.     mov bx,offset erms10a
  854.     call errpack        ; Send error packet just in case
  855.     jmp abort        ; Change the state to abort
  856.  
  857. rdat12: inc pack.oldtry        ; Save the updated number of tries
  858.     mov ax,pack.pktnum
  859.     cmp ax,0        ; Had we wrapped around? [18 start]
  860.     jne rdatx
  861.  
  862.     mov ax,64
  863.  
  864. rdatx:    dec ax            ; [14] [18 end -- new label]
  865.     cmp ax,pack.argblk    ; Is the packet's number one less than now?
  866.     je rdat13
  867.  
  868.     jmp nak0        ; No, NAK it and try again
  869.  
  870. rdat13: call updrtr        ; Update retry count
  871.     mov pack.numtry,0    ; Reset number of tries
  872.     mov pack.argbk1,0    ; No data.  (The packet number is in argblk.)
  873.     mov cx,0
  874.     call doenc
  875.     mov ah,'Y'        ; Acknowledge packet
  876.     call spack        ; Send the packet
  877.      jmp Abort
  878.  
  879.     ret
  880.  
  881. rdat14: inc ax            ; Increment the packet number
  882.     and ax,3FH        ; Turn off the two high order bits
  883.     mov pack.pktnum,ax    ; Save modulo 64 of the number
  884.     inc pack.numpkt        ; Increment the number of packets
  885.     mov ah,pack.numtry    ; Get the number of tries
  886.     mov pack.oldtry,ah    ; Save it
  887.     mov ax,pack.argbk1    ; Get the length of the data
  888.     cmp flags.cxzflg,0    ; Has the user typed a ^X or ^Z? [20c]
  889.     je rdt14x        ; No, write out the data
  890.  
  891.     cmp flags.abfflg,1    ; Discard incomplete files?
  892.     je rdat15        ; If yes don't write data out to file. [20c]
  893.  
  894. rdt14x:    mov bx,offset data    ; Where the data is. [25]
  895.     call ptchr
  896.      jmp Abort        ;  Unable to write out chars
  897.  
  898. rdat15: mov pack.numtry,0    ; Reset the number of tries
  899.     mov pack.argbk1,0    ; No data.  (Packet number still in argblk.)
  900.     mov cx,0
  901.     cmp flags.cxzflg,0    ; Interrupt file transfer? [20c]
  902.     je rdat16        ; Nope. [20c] 
  903.  
  904.     mov bx,offset data    ; Send data in ACK in case remote... [20c] 
  905.     mov ah,flags.cxzflg    ; ... knows about ^X/^Z. [20c]
  906.     mov [bx],ah        ; Put data into the packet. [20c]
  907.     mov pack.argbk1,1    ; Set data size to 1. [20c]
  908.     mov cx,1
  909.  
  910. rdat16: call doenc
  911.     mov ah,'Y'        ; Acknowledge packet
  912.     call spack        ; Send the packet
  913.      jmp Abort
  914.  
  915.     ret
  916.  
  917. rdata2: cmp ah,'F'        ; Start of file?
  918.     je rdat20        ; Yup. [21c]
  919.  
  920.     cmp ah,'X'        ; Text header packet? [21c]
  921.     jne rdata3        ;  No, try next type
  922.  
  923. rdat20: cmp pack.oldtry,maxtry    ; Reached the max number of tries? [21c]
  924.     jl rdat21        ; If not proceed
  925.  
  926.     mov dx,offset ermes8
  927.     call Show_error        ; Display message
  928.     mov bx,offset ermes8a
  929.     call errpack        ; Send error packet just in case
  930.     jmp abort        ; Change the state to abort
  931.  
  932. rdat21: inc pack.oldtry        ; Save the updated number of tries
  933.     mov ax,pack.pktnum
  934.     cmp ax,0        ; Had we wrapped around? [18 start]
  935.     jne rdaty
  936.  
  937.     mov ax,64
  938.  
  939. rdaty:    dec ax            ; [14 Omitted accidentally - D.T.] [18 end]
  940.     cmp ax,pack.argblk    ; Is the packet's number one less than now?
  941.     je rdat22
  942.  
  943.     jmp nak0        ; No, NAK it and try again
  944.  
  945. rdat22: call updrtr        ; Update retry count
  946.     mov pack.numtry,0    ; Reset number of tries
  947.     mov pack.argbk1,0    ; No data.  (The packet number is in argblk.)
  948.     mov cx,0
  949.     call doenc
  950.     mov ah,'Y'        ; Acknowledge packet
  951.  
  952.     call spack        ; Send the packet
  953.      jmp Abort
  954.  
  955.     ret
  956.  
  957. rdata3: cmp ah,'Z'        ; Is it a EOF packet?
  958.     je rdat3x        ; [13]
  959.  
  960.     jmp rdata4        ; Try and see if its an error. [13]
  961.  
  962. rdat3x: mov ax,pack.pktnum    ; Get the present packet number. [13]
  963.     cmp ax,pack.argblk    ; Is the packet's number correct?
  964.     je rdat32
  965.  
  966.     jmp nak0        ; No, NAK it and try again
  967.  
  968. rdat32: inc ax            ; Increment the packet number
  969.     and ax,3FH        ; Turn off the two high order bits
  970.     mov pack.pktnum,ax    ; Save modulo 64 of the number
  971.     inc pack.numpkt
  972.     cmp flags.cxzflg,0    ; Do we want to discard the file? [20c]
  973.     jne rdt32x        ; Yes. [20c]
  974.  
  975.     cmp pack.argbk1,1    ; One piece of data? [20c]
  976.     jne rdat33        ; Nope - finish writing out file? [20c]
  977.  
  978.     mov bx,offset data    ; Get data area. [20c]
  979.     mov ah,[bx]        ; Get the data. [20c]
  980.     cmp ah,'D'        ; "D" for discard? [20c]
  981.     jne rdat33        ; Nope - write out file. [20c]
  982.  
  983. rdt32x:    cmp flags.abfflg,0    ; Keep incomplete files?
  984.     je rdat33        ; Yes, go write it out
  985.  
  986.     PUBLIC MSRECV_close_file_1
  987.  
  988. MSRECV_close_file_1:
  989.     mov ah,closf        ; First, close the file
  990.     mov dx,offset fcb    ; Give the file parameters. [20c]
  991.     int dos            ; Kill it, ignore errors. [20c]
  992.  
  993.     mov ah,delf        ; Delete the file if opened. [20c]
  994.     int dos
  995.  
  996.     cmp flags.cxzflg,'X'    ; Kill one file or all? [20c]
  997.     jne rdat36        ; No so leave flag alone. [20c]
  998.  
  999.     call cxmsg        ; Clear msg about interrupt. [20c]
  1000.     mov flags.cxzflg,0    ; Reset - ^X only kills one file. [20c]
  1001.     jmp rdat36
  1002.  
  1003.     PUBLIC rdat33
  1004.  
  1005. rdat33: mov bx,bufpnt        ; Get the dma pointer
  1006.     mov ax,80H
  1007.     sub ax,chrcnt        ; Get the number of chars left in the DMA
  1008.     cmp flags.eofcz,0    ; should we write a ^Z?
  1009.     jz rdat35        ; no, keep going
  1010.  
  1011.     cmp flags.xflg,0    ; writing to a file?
  1012.     jne rdat35        ; no, skip ^Z
  1013.  
  1014.     cmp ax,80H        ;   [13 start]
  1015.     jne rdat34
  1016.  
  1017.     call outbuf        ; Write out buffer if no room for ^Z
  1018.      jmp abort
  1019.  
  1020.     mov ax,0        ;   [13 end]
  1021.     inc chrcnt        ; Increment size by one (not two). [21b]
  1022.  
  1023. rdat34: mov cl,'Z'-100O        ; Put in a ^Z for EOF
  1024.     mov [bx],cl        ; Add it. [21c]
  1025.     inc ax
  1026.     dec chrcnt
  1027.  
  1028. rdat35:    mov cx,chrcnt
  1029.     mov temp,cx
  1030.     call outbuf        ; Output the last buffer
  1031.      jmp abort        ; Give up if the disk is full
  1032.     mov ax,temp        ; Prepare for the function call
  1033.     call fixfcb
  1034.  
  1035.     cmp Flags.XFlg, 0    ; Writing to screen?
  1036.      je MSRECV_close_file_2    ;  No, go close the file
  1037.  
  1038.     mov ah, PrStr        ; Code to write to screen
  1039.     mov dx, OFFSET CrLf    ; A CrLf
  1040.     int Dos            ; Type it
  1041.  
  1042.     mov ah, PrStr        ; Code to write to screen
  1043.     mov dx, OFFSET CrLf    ; A CrLf
  1044.     int Dos            ; Type another CrLf
  1045.  
  1046.     jmp SHORT rdat37    ; Skip over this code
  1047.  
  1048.     PUBLIC MSRECV_close_file_2
  1049.  
  1050. MSRECV_close_file_2:
  1051.     mov ah,closf        ; Close up the file
  1052.     mov dx,offset fcb
  1053.     int dos
  1054.  
  1055. rdat36:    cmp flags.destflg,1    ; Writing to disk?
  1056.     je rdat37        ; Yes, skip next part
  1057.     cmp flags.xflg,1    ; Writing to screen?
  1058.     je rdat37        ; Yes, skip this part
  1059.     mov dl,ff        ; Send a form feed
  1060.     mov ah,lstout        ; Write out to first printer
  1061.     int dos
  1062.  
  1063. rdat37:    mov ah,pack.numtry    ; Get the number of tries
  1064.     mov pack.oldtry,ah    ; Save it
  1065.     mov pack.numtry,0    ; Reset the number of tries
  1066.     mov pack.argbk1,0    ; No data.  (The packet number is in argblk.)
  1067.     mov cx,0
  1068.     call doenc
  1069.     mov ah,'Y'        ; Acknowledge packet
  1070.     call spack        ; Send the packet
  1071.      jmp abort
  1072.     mov pack.state,'F'
  1073.     ret
  1074. rdata4: cmp ah,'E'            ; Is it an error packet
  1075.     jne rdata5
  1076.     call error
  1077. rdata5: jmp abort
  1078. RDATA    ENDP
  1079.  
  1080.  
  1081. ABORT   PROC
  1082.  
  1083.     mov pack.state,'A'      ; Otherwise abort
  1084.     ret
  1085.  
  1086. ABORT   ENDP
  1087.  
  1088.  
  1089. ; Jumping to this location is like retskp.  It assumes the instruction
  1090. ;   after the call is a jmp addr
  1091.  
  1092. RSKP    PROC    NEAR
  1093.     pop bp
  1094.     add bp,3
  1095.     push bp
  1096. ;    ret
  1097. RSKP    ENDP
  1098.  
  1099. R    PROC    NEAR
  1100.     ret
  1101. R    ENDP
  1102.  
  1103. code    ends 
  1104.     END
  1105. 
  1106.